package com.hugang.reflect.invoke;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 调用运行时类中指定的结构：属性、方法、构造器
 *
 * @author hg
 * @date 2020/6/23 21:39
 */
public class InvokeTest {

    @Test
    public void testField() throws Exception {
        Class clazz = Person.class;
        Person person = (Person) clazz.newInstance();
        //获取指定的属性
//        Field id = clazz.getField("id");
        Field id = clazz.getField("age");

        //设置当前属性的值
        id.set(person, 1001);

        //获取当前属性的值
        int pId = (int) id.get(person);

        System.out.println(pId);
    }

    @Test
    public void testField2() throws Exception {
        Class clazz = Person.class;
        Person person = (Person) clazz.newInstance();
        Field age = clazz.getDeclaredField("age");
        age.set(person, 124);
        System.out.println(age.get(person));

        //调用私有属性需要设置当前属性值为可访问，即：setAccessable(true)
        Field name = clazz.getDeclaredField("name");
        name.setAccessible(true);
        name.set(person, "124");
        System.out.println(name.get(person));

    }

    /**
     * 操作运行时类中的指定方法
     * @throws Exception
     */
    @Test
    public void testMethod() throws Exception{
        Class clazz = Person.class;

        //创建运行时类的对象
        Person person = (Person) clazz.newInstance();

        //非静态
        //1、获取指定的某个方法
        Method show = clazz.getDeclaredMethod("show", String.class);

        //2、保证当前方法是可访问的
        show.setAccessible(true);

        //3、调用此对象的此方法
        //invoke()的返回值即对应类中调用的方法的返回值
        Object china = show.invoke(person, "china");
        System.out.println(china);

        //静态方法
        Method showDesc = clazz.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
        showDesc.invoke(null);


    }

    /**
     * 操作运行时类中的构造器
     * @throws Exception
     */
    @Test
    public void testConstructor() throws Exception{
        Class clazz = Person.class;
        //1、获取指定构造器
        Constructor constructor = clazz.getDeclaredConstructor(String.class);

        //2、保证此构造器能访问
        constructor.setAccessible(true);

        //3、调用此构造器创建运行时类的对象
        Object o = constructor.newInstance("张三");

        System.out.println(o);


    }


}
